/*
 * correlation.c
 * Created on August 4, 2005; 5:30 PM
 * by vramadurai
 */
#include <stdio.h>
#include <stdlib.h>

/************ Private Header Files **************/
#include "HsTypes.h"
#include "PhyDebug.h"
#include "PhyStruct.h"
#include "PmdGlobals.h"
#include "PhyConstants.h"
#include "iqdma_3500.h"
#include "rx_functions.h"
#include "correlation.h"
#include "training.h"
#include "tables.h"

#if 1
static
hs_uint32_t correlation(
                    hs_int16_t * restrict psSyncBufI,
                    hs_int16_t * restrict psSyncBufQ,
                    hs_int16_t * restrict psUpSampBarkerSeq,
                    hs_int32_t *siReadPtr
                )
{
    hs_int16_t MaxCorrVal;

    hs_int16_t AbsCorrVal[32];

    hs_int32_t siIndex1;
    hs_int32_t siIndex;
    hs_int32_t siCorrValI;
    hs_int32_t siCorrValQ;
    hs_int16_t ssCorrValI;
    hs_int16_t ssCorrValQ;

    MaxCorrVal = 0;

    for(siIndex1 = 0; siIndex1 < 22; siIndex1++)
    {
        hs_int16_t *syncbufI = &psSyncBufI[siIndex1];
        hs_int16_t *syncbufQ = &psSyncBufQ[siIndex1];

        siCorrValI = 0;
        siCorrValQ = 0;

        for(siIndex = 0; siIndex < 24; siIndex++)
        {
            siCorrValI += (syncbufI[siIndex] * psUpSampBarkerSeq[siIndex]);
            siCorrValQ += (syncbufQ[siIndex] * psUpSampBarkerSeq[siIndex]);
        }
        ssCorrValI = siCorrValI >> 16;
        ssCorrValQ = siCorrValQ >> 16;

        AbsCorrVal[siIndex1] = (ssCorrValI*ssCorrValI)+(ssCorrValQ*ssCorrValQ) >> 16;
    }

    for(siIndex1 = 0; siIndex1 < 22; siIndex1++)
    {
        if(AbsCorrVal[siIndex1] > MaxCorrVal)
        {
            MaxCorrVal = AbsCorrVal[siIndex1];
            *siReadPtr    = siIndex1;
        }
    }

    return MaxCorrVal;
}
#endif 

/** symbol buffering and correlation: Performed by thread1 and thread2 **/
void wlan_do_buffer_for_correlation(
                                struct HS_Phy11bStr  *HS_Phy11bPtrTh,
                                hs_int16_t  * restrict psSyncBufI,
                                hs_int16_t  * restrict psSyncBufQ,
                                ePHYSTATES_TH *ePhyState
                              )
{
    /** wait for the buffer pointer to be updated by the prev thread **/
    sync_on_dma((hs_int32_t)HS_Phy11bPtrTh->piRdPtrI, 88);

    START_CLOCK

    rx_copysamps44(HS_Phy11bPtrTh, psSyncBufI, psSyncBufQ);
    *ePhyState = PHY_RX_COARSE_SYNC_CORR_TH ;

    PRINT_CYCLES("buffer for correlation");
}

void update_read_ptr(
                        struct HS_Phy11bStr  * HS_Phy11bPtrTh
                    )
{
    hs_int32_t  siOffset;

    hs_int16_t  *piEndPtrI = HS_Phy11bPtrTh->piEndPtrI;
    hs_int16_t  *piStartPtrI = HS_Phy11bPtrTh->piStartPtrI;
    hs_int16_t  *piStartPtrQ = HS_Phy11bPtrTh->piStartPtrQ;

    siOffset = (hs_int32_t)(HS_Phy11bPtrTh->piRdPtrI + (HS_Phy11bPtrTh->siReadPtr+44) - piEndPtrI);
    if(siOffset >= 0)
    {
        HS_Phy11bPtrTh->piRdPtrI = piStartPtrI + siOffset;
        HS_Phy11bPtrTh->piRdPtrQ = piStartPtrQ + siOffset;
    }
    else
    {
      HS_Phy11bPtrTh->piRdPtrI += (HS_Phy11bPtrTh->siReadPtr+44);
      HS_Phy11bPtrTh->piRdPtrQ += (HS_Phy11bPtrTh->siReadPtr+44);
    }
}

void do_correlation_th1(
                        struct HS_Phy11bStr  *HS_Phy11bPtrTh,
                        hs_int16_t  * restrict psUpSampBarkerSeq,
                        hs_int16_t  * restrict psSyncBufI,
                        hs_int16_t  * restrict psSyncBufQ,
                        ePHYSTATES_TH *ePhyState
                    )
{
    /* 22 Correlations are computed and the find the Max correlation*/
    HS_Phy11bPtrTh->siReadPtr = 0;

    START_CLOCK
    //correlation_asm(psSyncBufI, psSyncBufQ, psUpSampBarkerSeq, &HS_Phy11bPtrTh->siReadPtr);
    correlation(psSyncBufI, psSyncBufQ, psUpSampBarkerSeq, &HS_Phy11bPtrTh->siReadPtr);

    update_read_ptr(HS_Phy11bPtrTh);
    PRINT_CYCLES("barker correlation");
    *ePhyState  = PHY_RX_GET_SYMBOL;
}
